#==============================================================================
#
#  $Id$
#
"""
    Abstract interfaces for database classes.
"""
#
#  Copyright (C) 2006 Michael A. Muller
#  Portions Copyright 2008 Google Inc.
#
#   This file is part of ODB.
#
#   ODB is free software: you can redistribute it and/or modify it under the 
#   terms of the GNU Lesser General Public License as published by the Free 
#   Software Foundation, either version 3 of the License, or (at your option) 
#   any later version.
#
#   ODB is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU Lesser General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public License 
#   along with ODB.  If not, see <http://www.gnu.org/licenses/>.
#
#==============================================================================


class DB:
   """
      Interface for a database.
   """

   def cursor(self, txn = None):
      """
         Returns a cursor on the database.
      """
      raise NotImplementedError()

   def getTxn(self):
      """
	 Creates a transaction on the underlying environment and returns it.
	 
	 Transactions are created for an entire environment - not individual 
	 databases.  This method is provided purely as a convenience.
      """
      raise NotImplementedError()
   
   def close(self):
      """
         Close the database.
      """
      raise NotImplementedError()

class Cursor:
   """
      Interface for a cursor.
   """

   def setToFirst(self):
      """
	 Sets the cursor to the first entry in the database.
      """
      raise NotImplementedError()

   def setToLast(self):
      """
         Sets the cursor to the last entry in the database.
      """
      raise NotImplementedError()

   def setToKey(self, key, exact = False):
      """
	 Sets the cursor to the record identified by the key.  The key is
	 assumed to be a partial key unlss you specify otherwise by setting 
	 "exact" to true.

	 If an exact match is specified and the key is not matched, raises a
	 *KeyError*

	 parms:
	    key::
	       [string] the complete or partial key
	    exact::
	       [boolean] if true, will match only an exact match.  Otherwise,
	       matches the first key that is greater than or equal to the key.

	       *Note,* this behavior only works on BTree's - on other types of
	       databases all matches will be exact.
      """
      raise NotImplementedError()

   def next(self):
      """
	 Returns the next key/value pair referenced by the cursor and
	 increments it.  Raises *StopIteration* if we're at the end of
	 iteration.
      """
      raise NotImplementedError()

   def __iter__(self):
      """
	 Returns "self" so that the cursor to be iterated in a for loop:

	 {{
	    for key, val in cursor:
	       ...
	 }}
      """
      raise NotImplementedError()

   def reverse(self):
      """
         Returns a reverse cursor from the position of this cursor.
      """
      return ReverseCursor(self)

class ReverseCursor:

   """
      Wraps cursor to allow reverse iteration from a for loop.
   """

   def __init__(self, cursor):
      """
         Create a reverse cursor from an existing forward cursor.
      """
      self.__cur = cursor

   def next(self):
      """
         Returns a key/value pair for the previous item in the index.
      """
      return self.__cur.prev()

   def __iter__(self):
      """
         Returns "self" so we can say "for x in ReverseCursor(db.cursor())"
      """
      return self

class KeyDB(DB):
   """
      A data base that is accessible by a key.  All of the standard dictionary
      access methods are supported.
   """
   def __getitem__(self, key):
      raise NotImplementedError()

   def get(self, key, default = None, txn = None):
      raise NotImplementedError()

   def has_key(self, key):
      raise NotImplementedError()

   def __delitem__(self, key):
      raise NotImplementedError()

   def delete(self, txn, key):
      """
         Delete the specified key.  If the table supports duplicates, this 
         will delete the first occurrence of the key.
         
         parms:
            txn: [@Txn] transaction for the delete.
            key: [string] key to delete.
      """
      raise NotImplementedError()

   def __setitem__(self, key, val):
      raise NotImplementedError()

   def set(self, txn, key, val):
      """
         Set the key to the specified value.  If the table supports 
         duplicates, this will insert the key/value, otherwise it will replace 
         it.
         
         parms:
            txn: [@Txn] transaction for the insert/replace.
            key: [string] the key to store under
            val: [any] the value to store.  Must be pickleable.
      """
      raise NotImplementedError()

class Env:
   """
      A database environment.  Groups together a set of databases.
   """

   def __init__(self, path, recover = False):
      raise NotImplementedError()

   def getBTreeDB(self, name, allowDups = False):
      """
         Returns the specified BTree database (derived from @KeyDB), creating 
         it if necessary.
         
         It is an error condition to use this on an existing database of the 
         same name that is not a b-tree or does not have the same value for 
         allowDups.
         
         parms:
            allowDups: [boolean] if true, allow multiple items to be stored 
               under the same key.
      """
      raise NotImplementedError()

   def getHashDB(self, name, allowDups = False):
      """
         Returns the specified hash-table database (derived from @KeyDB), 
         creating it if necessary.

         It is an error condition to use this on an existing database of the 
         same name that is not a hashtable or does not have the same value for 
         allowDups.
         
         parms:
            name: [string] the database name.
            allowDups: [boolean] if true, allow multiple items to be stored 
               under the same key.
      """
      raise NotImplementedError()

   def checkpoint(self):
      """
         Force writing a checkpoint (for databases that support it - default
         implementation does nothing).
      """
      pass

   def getTxn(self):
      """
         Returns a new transaction for the environment.  This is a raw BDB
         transaction.  See the @Txn class for documentation.
      """
      raise NotImplementedError()
   
   def close(self):
      """
         Close the entire environment.
      """
      raise NotImplementedError()

class Txn:
   """
      A transaction.
   """

   def abort(self):
      """
         Abort the transaction, rollback all activities.
      """
      raise NotImplementedError()

   def commit(self):
      """
         Commit the transaction.
      """
      raise NotImplementedError()


